/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 * MemCache_Hybrid is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
*/
#ifndef MEM_FABRIC_MMC_MEM_OBJ_META_H
#define MEM_FABRIC_MMC_MEM_OBJ_META_H

#include <vector>
#include <mutex>
#include <list>

#include "mmc_mem_blob.h"
#include "mmc_meta_lease_manager.h"
#include "mmc_montotonic.h"
#include "mmc_msg_packer.h"
#include "mmc_ref.h"
#include "mmc_spinlock.h"
#include "mmc_global_allocator.h"

namespace ock {
namespace mmc {

class MmcMemObjMeta : public MmcReferable {
public:
    MmcMemObjMeta() = default;
    MmcMemObjMeta(uint16_t prot, uint8_t priority, std::vector<MmcMemBlobPtr> blobs,
                  uint64_t size)
        : prot_(prot), priority_(priority)
    {
        for (auto &blob : blobs) {
            AddBlob(blob);
        }
    }
    ~MmcMemObjMeta() override = default;

    /**
     * @brief Add blob info into the mem object,
     * for replicated blob on different rank ids
     *
     * @param blob         [in] blob pointer to be added
     */
    Result AddBlob(const MmcMemBlobPtr &blob);

    /**
     * @brief Free blobs from the mem object by filter
     *
     * @param allocator allocator ptr
     * @return 0 if removed
     */
    Result FreeBlobs(const std::string &key, MmcGlobalAllocatorPtr &allocator,
                     const MmcBlobFilterPtr &filter = nullptr, bool doBackupRemove = true);

    /**
     * @brief Get the prot
     * @return prot
     */
    uint16_t Prot();

    /**
     * @brief Get the priority
     * @return priority
     */
    uint8_t Priority();

    /**
     * @brief Get the number of blobs
     * @return number of blobs
     */
    uint16_t NumBlobs();

    /**
     * @brief Get blobs with filter
     * @return blobs passing the filter
     */
    std::vector<MmcMemBlobPtr> GetBlobs(const MmcBlobFilterPtr &filter = nullptr, bool revert = false);

    void GetBlobsDesc(std::vector<MmcMemBlobDesc>& blobsDesc, const MmcBlobFilterPtr& filter = nullptr,
                      bool revert = false);

    Result UpdateBlobsState(const std::string& key, const MmcBlobFilterPtr& filter, uint64_t operateId,
                            BlobActionResult actRet);

    /**
     * @brief Get the size
     * @return size
     */
    uint64_t Size();

    /**
     * @brief move to next level
     * @return size
     */
    MediaType MoveTo(bool down);

    friend std::ostream& operator<<(std::ostream& os, const MmcMemObjMeta& obj)
    {
        os << "MmcMemObjMeta{numBlobs=" << static_cast<int>(obj.numBlobs_) << ",size=" << obj.size_
           << ",priority=" << static_cast<int>(obj.priority_) << ",prot=" << obj.prot_ << "}";

        for (const auto& blob : obj.blobs_) {
            os << blob;
        }

        return os;
    }

    friend std::ostream& operator<<(std::ostream& os, const MmcRef<MmcMemObjMeta>& obj) { return os << *obj.Get(); }

private:
    Result RemoveBlobs(const MmcBlobFilterPtr &filter = nullptr, bool revert = false);

private:
    /* make sure the size of this class is 64 bytes */
    uint16_t prot_{0};                         /* prot of the mem object, i.e. accessibility */
    uint8_t priority_{0};                      /* priority of the memory object, used for eviction */
    uint8_t numBlobs_{0};                      /* number of blob that the memory object, i.e. replica count */
    std::list<MmcMemBlobPtr> blobs_;           /* 24 bytes */
    uint64_t size_{0};                         /* byteSize of each blob */
};

using MmcMemObjMetaPtr = MmcRef<MmcMemObjMeta>;

inline uint16_t MmcMemObjMeta::Prot()
{
    return prot_;
}

inline uint8_t MmcMemObjMeta::Priority()
{
    return priority_;
}

inline uint16_t MmcMemObjMeta::NumBlobs()
{
    return numBlobs_;
}

inline uint64_t MmcMemObjMeta::Size()
{
    return size_;
}

}  // namespace mmc
}  // namespace ock

#endif  // MEM_FABRIC_MMC_MEM_OBJ_META_H